package com.zg.sso.util;

import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;

import javax.crypto.Cipher;
import java.io.ByteArrayOutputStream;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Base64;

public class RSAUtil {
    private static final String RSA_ALGORITHM = "RSA";
    public static final String ECB_PKCS1_PADDING = "RSA/ECB/PKCS1Padding";//加密填充方式
    private static final int MAX_ENCRYPT_BLOCK = 117;
    /**
     * 随机生成密钥对
     * @throws NoSuchAlgorithmException
     */
    public static String[] genKeyPair() throws Exception {
        // KeyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance(RSA_ALGORITHM);
        // 初始化密钥对生成器，密钥大小为96-1024位
        keyPairGen.initialize(1024,new SecureRandom());
        // 生成一个密钥对，保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        // 得到私钥
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();
        // 得到公钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();
        String publicKeyString = new String(Base64.getEncoder().encode(publicKey.getEncoded()));
        // 得到私钥字符串
        String privateKeyString = new String(Base64.getEncoder().encode((privateKey.getEncoded())));
        System.out.println("公钥字符串:"+publicKeyString);
        System.out.println("私钥字符串:"+privateKeyString);
        return new String[]{publicKeyString,privateKeyString};
    }

    //RSA公钥解密
    public static String decrypt(String encryptedString, String publicKey) throws Exception {
        byte[] decode = Base64.getDecoder().decode(publicKey);
        X509EncodedKeySpec x509EncodedKeySpec = new X509EncodedKeySpec(decode);
        KeyFactory kf = KeyFactory.getInstance(RSA_ALGORITHM);
        PublicKey generatePublic = kf.generatePublic(x509EncodedKeySpec);
        Cipher ci = Cipher.getInstance(RSA_ALGORITHM);
        ci.init(Cipher.DECRYPT_MODE,generatePublic);

        byte[] bytes = Base64.getDecoder().decode(encryptedString.replaceAll(" ","+"));
        int inputLen = bytes.length;
        int offLen = 0;
        int i = 0;
        ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
        while(inputLen - offLen > 0){
            byte[] cache;
            if(inputLen - offLen > 128){
                cache = ci.doFinal(bytes,offLen,128);
            }else{
                cache = ci.doFinal(bytes,offLen,inputLen - offLen);
            }
            byteArrayOutputStream.write(cache);
            i++;
            offLen = 128 * i;

        }
        byteArrayOutputStream.close();
        byte[] byteArray = byteArrayOutputStream.toByteArray();
        return new String(byteArray);
    }
    //RSA公钥加密
    public static String encrypt(String source, String pubKey) throws Exception {
        Key publicKey = generatePublicKey(pubKey);
        /** 得到Cipher对象来实现对源数据的RSA加密 */
        Cipher cipher = Cipher.getInstance(ECB_PKCS1_PADDING);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        byte[] data = source.getBytes();
        /** 执行分组加密操作 */
        int inputLen = data.length;
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        int offSet = 0;
        byte[] cache;
        int i = 0;
        // 对数据分段加密
        while (inputLen - offSet > 0) {
            if (inputLen - offSet > MAX_ENCRYPT_BLOCK) {
                cache = cipher.doFinal(data, offSet, MAX_ENCRYPT_BLOCK);
            } else {
                cache = cipher.doFinal(data, offSet, inputLen - offSet);
            }
            out.write(cache, 0, cache.length);
            i++;
            offSet = i * MAX_ENCRYPT_BLOCK;
        }
        byte[] encryptedData = out.toByteArray();
        out.close();

        BASE64Encoder encoder = new BASE64Encoder();
        return encoder.encode(encryptedData);
    }
    //公钥字符串转为公钥对象
    private static Key generatePublicKey(String publicKeyStr) throws Exception {
            BASE64Decoder base64Decoder = new BASE64Decoder();
            byte[] buffer = base64Decoder.decodeBuffer(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return keyFactory.generatePublic(keySpec);
    }
    //私钥字符串转为私钥对象
    private static Key generatePrivateKey(String privateKeyStr) throws Exception{
        byte[] decodedBytes = Base64.getDecoder().decode(privateKeyStr);
        PKCS8EncodedKeySpec privateKeySpec = new PKCS8EncodedKeySpec(decodedBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(RSA_ALGORITHM);
        return keyFactory.generatePrivate(privateKeySpec);
    }

    //使用私钥加密
    public static String encryptWithPrivateKey(String plainText, String privateKey) throws Exception {
        Key key = generatePrivateKey(privateKey);
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.ENCRYPT_MODE, key);
        byte[] encrypted = cipher.doFinal(plainText.getBytes());
        return Base64.getEncoder().encodeToString(encrypted);
    }
    //使用私钥解密
    public static String decryptWithPrivateKey(String encryptedText, String privateKey) throws Exception {
        byte[] encryptedBytes = Base64.getMimeDecoder().decode(encryptedText);
        Key key = generatePrivateKey(privateKey);
        Cipher cipher = Cipher.getInstance(RSA_ALGORITHM);
        cipher.init(Cipher.DECRYPT_MODE, key);
        byte[] decryptedBytes = cipher.doFinal(encryptedBytes);
        return new String(decryptedBytes);
    }

    public static void main(String[] args) throws Exception {
        //genKeyPair();
        String privateKeyStr = "MIICeQIBADANBgkqhkiG9w0BAQEFAASCAmMwggJfAgEAAoGBAK9M4KBhhpWH2YVblops4iPzmIkf3iZzBeC9TmFeMcXgyM9RZbmBFBRcswUB4md1vtRiksumRRoU+iOA32TTs2M6Au2VddnSsPmZAl8fXap/pKhoogxRPfUbOlK8aVuJVe4KefoYlCjjkDeTDyT6fsri6FQhYQhBbvpR10UIrilpAgMBAAECgYEAipaYr7Lql6UDDy9NYLqcPhgDa8VJ99PPvdFr+gZiCzKfD2gmp/WoTkDLNxY6S9kGuRoFPAODdg9HgnIMKsZDdso/i8xN9x6TpYGFz27tZ/cwqWus4Li1juEChUmnKVWilNzR84Q0+pw/o3PRicyHKwIRwwiy0kgEUq3NdXj+M5ECQQDrZgToQLkE2bPyX+gY706Gl81amGuHQGY12LGfnbFlGYryaTJiOgORw6p5wzYHRX8X2z05KWez0hMYWt9NzoJrAkEAvqRjpb91IiOyuKmdXPjyv2VvEGDN17H7zSnxh8ZLO2ZBEFLykbo5KAHgEdxMuAvciW5/5lmvZsi0xuUb/8CAewJBAKnvARXlO2vb+YK8Z6Iwh8C0L6P6Ko3+GItAvqGaxmhUszDibmPou5Dr7tJt8T/4lJJVS/JLCLkQq4ZGe7QAo7cCQQCV8MNzBH+DB2K0vKrJCgAaqxPMZObhA9qQxbFy4XIgWM9JoIOqPDZiEf+C7KrmgmXFLcSojtdW1vrgCCiaYXRrAkEA5U4EwkU2P2CujHLBVJ/VfJ/kGhy6ajQ0UHLjcDy7iDz4MCcx1oucT+9hpPLhlW3H2mG5YxKZ+l3Tb9BDejpp/A==";
        String publicKeyStr = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQCvTOCgYYaVh9mFW5aKbOIj85iJH94mcwXgvU5hXjHF4MjPUWW5gRQUXLMFAeJndb7UYpLLpkUaFPojgN9k07NjOgLtlXXZ0rD5mQJfH12qf6SoaKIMUT31GzpSvGlbiVXuCnn6GJQo45A3kw8k+n7K4uhUIWEIQW76UddFCK4paQIDAQAB";
//        String ciphertext = encryptWithPrivateKey("南王庄",privateKeyStr);
//        System.out.println("私钥加密："+ciphertext);
//        String plainText = decrypt(ciphertext,publicKeyStr);
//        System.out.println("公钥解密："+plainText);
//
//        String str = encrypt("xingtang",publicKeyStr);
//        System.out.println("公钥加密:"+str);
//        String str1 = decryptWithPrivateKey(str,privateKeyStr);
//        System.out.println("私钥解密:"+str1);
    }
}
